home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / GIFFEN.C < prev    next >
Text File  |  1990-02-28  |  9KB  |  364 lines

  1.  
  2. /*
  3.    GIF decompression for the Mac - put together by Kevin Parichan
  4.                                    using code and information from
  5.                                    David Rowley and Mac Tech Note #120
  6. */
  7.  
  8.  
  9. #include <ColorToolbox.h>
  10. #define NULL 0L
  11.  
  12. /********************************/
  13. /*       global variables       */
  14. /********************************/
  15.  
  16. Ptr        dataPtr,saveDataPtr,Raster;
  17. int        ImageWidth,ImageHeight;
  18. int        HasColorMap;
  19. long    BitsPerPixel,ColorMapSize,BitMask;
  20. long    ReadMask,CodeSize;
  21. long    BitOffset = 0;
  22. long    OutCount = 0;
  23. long    Pass = 0;
  24. int        XC = 0;
  25. int        YC = 0;
  26. int        Interlace;
  27. int        Prefix[4096];
  28. int        Suffix[4096];
  29. int        OutCode[1025];
  30.  
  31. PaletteHandle    thePalette = NULL;
  32. CWindowPtr        window;
  33. long            offRowBytes;
  34. Ptr                myBits;
  35.  
  36. /********************************/
  37. /*           #defines           */
  38. /********************************/
  39.  
  40. #define NEXTCHAR        (*dataPtr++)
  41. #define NEXTBYTE        (NEXTCHAR & 0xFF)
  42. #define NEXTSHORT        (NEXTBYTE + (0x100 * NEXTBYTE))
  43.  
  44. #define IMAGESEP        0x2C
  45. #define INTERLACEMASK    0x40
  46. #define COLORMAPMASK    0x80
  47.  
  48. #define palWindowSize    10
  49.  
  50. #define RASTER(bo)        (Raster[bo] & 0xFF)
  51.  
  52. /********************************/
  53. /*           routines           */
  54. /********************************/
  55.  
  56. long ReadCode()
  57. {
  58.    long RawCode,ByteOffset;
  59.    
  60.    ByteOffset = BitOffset / 8;
  61.    RawCode = RASTER(ByteOffset) + (0x100 * RASTER(ByteOffset + 1));
  62.    if (CodeSize >= 8)
  63.       RawCode += (0x10000 * RASTER(ByteOffset + 2));
  64.    RawCode >>= (BitOffset % 8);
  65.    BitOffset += CodeSize;
  66.    return(RawCode & ReadMask);
  67. }
  68.  
  69. AddToPixel(int index)
  70. {
  71.    myBits[YC*offRowBytes+XC] = (index & 0xFF);
  72.    
  73.    if (++XC == ImageWidth) {
  74.       XC = 0;
  75.       if (!Interlace)
  76.          YC++;
  77.       else {
  78.          switch (Pass) {
  79.             case 0:
  80.                YC += 8;
  81.                if (YC >= ImageHeight) {
  82.                   Pass++;
  83.                   YC = 4;
  84.                }
  85.                break;
  86.             case 1:
  87.                YC += 8;
  88.                if (YC >= ImageHeight) {
  89.                   Pass++;
  90.                   YC = 2;
  91.                }
  92.                break;
  93.             case 2:
  94.                YC += 4;
  95.                if (YC >= ImageHeight) {
  96.                   Pass++;
  97.                   YC = 1;
  98.                }
  99.                break;
  100.             case 3:
  101.                YC += 2;
  102.                break;
  103.             default:
  104.                break;
  105.          }
  106.       }
  107.    }
  108. }
  109.  
  110. typedef    BitMap    *BitMapPtr;
  111.  
  112. ReadGIF(Str255 fName, int vRefNum)
  113. {
  114.    long            fileSize,sizeOfOff;
  115.    int            ch,i,x,y,ch1,refNum,theDepth;
  116.    int            ImageLeft,ImageTop,ImageFlags;
  117.    RGBColor        color;
  118.    Rect            aRect,bRect,globRect;
  119.    long            ClearCode,EOFCode,FreeCode,FirstFree;
  120.    long            InitCodeSize,MaxCode,Code;
  121.    long            CurCode,OldCode,FinChar,InCode;
  122.    Ptr            ptr1;
  123.    OSErr        error;
  124.    CGrafPort    myCGrafPort;
  125.    CGrafPtr        myCGrafPtr;
  126.    CTabHandle    ourCMHandle;
  127.    GDHandle        theMaxDevice,oldDevice;
  128.    Point        tempP;
  129.    Str255        signature;
  130.    
  131.    BitOffset = OutCount = Pass = XC = YC = 0;    /* reset stuff */
  132.    
  133.    if (FSOpen(fName,vRefNum,&refNum)) return;
  134.    if (GetEOF(refNum,&fileSize)) { FSClose(refNum); return; }
  135.    if ((dataPtr = saveDataPtr = Raster = NewPtr(fileSize)) == NULL) { FSClose(refNum); return; }
  136.    if (FSRead(refNum,&fileSize,dataPtr)) { DisposPtr(saveDataPtr); FSClose(refNum); return; }
  137.    FSClose(refNum);
  138.    
  139.    signature[0] = 6;
  140.    for (i = 1; i <= 6; i++)
  141.       signature[i] = NEXTBYTE;
  142.    if (!EqualString(signature,"\pGIF87a",TRUE,TRUE)) { DisposPtr(saveDataPtr); return; }
  143.    
  144.    NEXTSHORT;    /* ignore screen width */
  145.    NEXTSHORT;    /* ignore screen height */
  146.    
  147.    ch = NEXTBYTE;
  148.    HasColorMap = ((ch & COLORMAPMASK) ? TRUE : FALSE);
  149.    BitsPerPixel = (ch & 7) + 1;
  150.    ColorMapSize = 1 << BitsPerPixel;
  151.    BitMask = ColorMapSize - 1;
  152.    
  153.    NEXTBYTE;    /* ignore background color */
  154.    NEXTBYTE;    /* end of GIF header */
  155.    
  156.    if (HasColorMap && ((thePalette = NewPalette(ColorMapSize,NULL,pmTolerant,0)) != NULL))
  157.       for (i = 0; i < ColorMapSize; i++) {
  158.          color.red = NEXTBYTE * 257;
  159.          color.green = NEXTBYTE * 257;
  160.          color.blue = NEXTBYTE * 257;
  161.          SetEntryColor(thePalette,i,&color);
  162.       }
  163.    
  164.    if (NEXTBYTE != IMAGESEP) {
  165.       if (thePalette != NULL) DisposePalette(thePalette);
  166.       DisposPtr(saveDataPtr);
  167.       return;
  168.    }
  169.    
  170.    ImageLeft = NEXTSHORT;
  171.    ImageTop = NEXTSHORT;
  172.    ImageWidth = NEXTBYTE;
  173.    ImageWidth = ImageWidth + (NEXTBYTE * 0x100);
  174.    ImageHeight = NEXTBYTE;
  175.    ImageHeight = ImageHeight + (NEXTBYTE * 0x100);
  176.    ImageFlags = NEXTBYTE;
  177.    Interlace = ((ImageFlags & INTERLACEMASK) ? TRUE : FALSE);
  178.    
  179.    SetRect(&aRect,0,0,palWindowSize*16+1,palWindowSize*16+1);
  180.    OffsetRect(&aRect,60,60);
  181.    window = (CWindowPtr)NewCWindow(NULL,&aRect,'',TRUE,3,(Ptr)(-1),FALSE,0);
  182.    SetPort(window);
  183.    if (thePalette != NULL) {
  184.       SetPalette(window,thePalette,TRUE);
  185.       ActivatePalette(window);
  186.    }
  187.    aRect = window->portRect;
  188.    for (i = 0 ; i < ColorMapSize ; i++)
  189.    {
  190.       PmForeColor(i);
  191.       x = (i % 16) * ((aRect.right-aRect.left) / 16) + 1;
  192.       y = (i / 16) * ((aRect.bottom-aRect.top) / 16) + 1;
  193.       SetRect(&bRect,x,y,x+((aRect.right-aRect.left) / 16) - 1,y + ((aRect.right-aRect.left) / 16) - 1);
  194.       PaintRect(&bRect);
  195.    }
  196.    while (!Button()) ;
  197.    while (Button()) ;
  198.    DisposeWindow(window);
  199.    
  200.    SetCursor(*GetCursor(watchCursor));
  201.    
  202.    SetRect(&aRect,0,0,ImageWidth,ImageHeight);
  203.    bRect = aRect;
  204.    OffsetRect(&aRect,10,30);
  205.    window = (CWindowPtr)NewCWindow(NULL,&aRect,'',TRUE,3,(Ptr)(-1),FALSE,0);
  206.    SetPort(window);
  207.    if (thePalette != NULL) {
  208.       SetPalette(window,thePalette,TRUE);
  209.       ActivatePalette(window);
  210.    }
  211.    
  212.    globRect = bRect;
  213.    tempP.v = globRect.top;
  214.    tempP.h = globRect.left;
  215.    LocalToGlobal(&tempP);
  216.    globRect.top = tempP.v;
  217.    globRect.left = tempP.h;
  218.    tempP.v = globRect.bottom;
  219.    tempP.h = globRect.right;
  220.    LocalToGlobal(&tempP);
  221.    globRect.bottom = tempP.v;
  222.    globRect.right = tempP.h;
  223.    theMaxDevice = GetMaxDevice(&globRect);
  224.    oldDevice = GetGDevice();
  225.    SetGDevice(theMaxDevice);
  226.    myCGrafPtr = &myCGrafPort;
  227.    OpenCPort(myCGrafPtr);
  228.    theDepth = (**(*myCGrafPtr).portPixMap).pixelSize;
  229.    offRowBytes = (((theDepth * ImageWidth) + 15) >> 4) << 1;
  230.    sizeOfOff = (long)ImageHeight * offRowBytes;
  231.    myBits = NewPtr(sizeOfOff);
  232.    (**(*myCGrafPtr).portPixMap).baseAddr = myBits;
  233.    (**(*myCGrafPtr).portPixMap).rowBytes = offRowBytes + 0x8000;
  234.    (**(*myCGrafPtr).portPixMap).bounds = bRect;
  235.    ourCMHandle = (**(**theMaxDevice).gdPMap).pmTable;
  236.    if (HandToHand(&ourCMHandle) != noErr) {
  237.       CloseCPort(myCGrafPtr);
  238.       SetGDevice(oldDevice);
  239.       if (thePalette != NULL) DisposePalette(thePalette);
  240.       DisposPtr(saveDataPtr);
  241.       return;
  242.    }
  243.    for (i = 0; i <= (**ourCMHandle).ctSize; ++i)
  244.       (**ourCMHandle).ctTable[i].value = i;
  245.    (**ourCMHandle).ctFlags &= 0x7FFF;
  246.    (**ourCMHandle).ctSeed = GetCTSeed();
  247.    if (thePalette != NULL)
  248.       Palette2CTab(thePalette,ourCMHandle);
  249.    (**(*myCGrafPtr).portPixMap).pmTable = ourCMHandle;
  250.    SetPort(myCGrafPtr);
  251.    
  252.    CodeSize = NEXTBYTE;
  253.    ClearCode = (1 << CodeSize);
  254.    EOFCode = ClearCode + 1;
  255.    FreeCode = FirstFree = ClearCode + 2;
  256.    
  257.    CodeSize++;
  258.    InitCodeSize = CodeSize;
  259.    MaxCode = (1 << CodeSize);
  260.    ReadMask = MaxCode - 1;
  261.    
  262.    ptr1 = Raster;
  263.    do {
  264.       ch = ch1 = NEXTBYTE;
  265.       while (ch--) *ptr1++ = NEXTBYTE;
  266.    } while (ch1);
  267.       
  268.    Code = ReadCode();
  269.    while (Code != EOFCode) {
  270.       if (Code == ClearCode) {
  271.          CodeSize = InitCodeSize;
  272.          MaxCode = (1 << CodeSize);
  273.          ReadMask = MaxCode - 1;
  274.          FreeCode = FirstFree;
  275.          CurCode = OldCode = Code = ReadCode();
  276.          FinChar = CurCode & BitMask;
  277.          AddToPixel(FinChar);
  278.       }
  279.       else {
  280.          CurCode = InCode = Code;
  281.          if (CurCode >= FreeCode) {
  282.             CurCode = OldCode;
  283.             OutCode[OutCount++] = FinChar;
  284.          }
  285.          while (CurCode > BitMask) {
  286.             OutCode[OutCount++] = Suffix[CurCode];
  287.             CurCode = Prefix[CurCode];
  288.          }
  289.          FinChar = CurCode & BitMask;
  290.          OutCode[OutCount++] = FinChar;
  291.          for (i = OutCount - 1; i >= 0; i--)
  292.             AddToPixel(OutCode[i]);
  293.          OutCount = 0;
  294.          Prefix[FreeCode] = OldCode;
  295.          Suffix[FreeCode] = FinChar;
  296.          OldCode = InCode;
  297.          FreeCode++;
  298.          if (FreeCode >= MaxCode) {
  299.             if (CodeSize < 12) {
  300.                CodeSize++;
  301.                MaxCode *= 2;
  302.                ReadMask = (1 << CodeSize) - 1;
  303.             }
  304.          }
  305.       }
  306.       Code = ReadCode();
  307.    }
  308.  
  309.    DisposPtr(saveDataPtr);
  310.    SetPort(window);
  311.    SetGDevice(oldDevice);
  312.    CopyBits((BitMapPtr)*(*myCGrafPtr).portPixMap,(BitMapPtr)*(*window).portPixMap,&bRect,&bRect,0,0L);
  313.    CloseCPort(myCGrafPtr);
  314.    DisposPtr(myBits);
  315.    DisposHandle(ourCMHandle);
  316.  
  317.    InitCursor();
  318.    while (!Button()) ;
  319.    while (Button()) ;
  320.  
  321.    DisposeWindow(window);
  322.    if (thePalette != NULL)
  323.       DisposePalette(thePalette);
  324. }
  325.  
  326. MainLoop()
  327. {
  328.   Point            where = {80,80};
  329.   SFTypeList    typeList;
  330.   SFReply        reply;
  331.  
  332.   typeList[0] = 'GIFf';
  333.   
  334.   do {
  335.     SFGetFile(where,'',NULL,1,&typeList,NULL,&reply);
  336.     if (reply.good)
  337.        ReadGIF(reply.fName,reply.vRefNum);
  338.   } while (reply.good);
  339. }
  340.  
  341. SetupMacintosh()
  342. {
  343.   MaxApplZone();
  344.   MoreMasters();
  345.   MoreMasters();
  346.   MoreMasters();
  347.   MoreMasters();
  348.  
  349.   InitGraf(&thePort);
  350.   InitFonts();
  351.   InitWindows();
  352.   InitMenus();
  353.   TEInit();
  354.   InitDialogs(NULL);
  355. }
  356.  
  357. main()
  358. {
  359.   SetupMacintosh();
  360.   InitCursor();
  361.   
  362.   MainLoop();
  363. }
  364.